﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;

using Csla;
using Csla.Core;
using Csla.Security;
using Csla.Rules;
using Csla.Rules.CommonRules;

using Haushaltsbuch.DataAcces;
using Haushaltsbuch.DataAcces.Entities;

using Microsoft.Build.Framework;






namespace Haushaltsbuch.Domain.Users
{
    [Serializable]
    public class UserEdit : BusinessBase<UserEdit>
    {
        private static readonly PropertyInfo<RoleEditList> RolesProperty =
            RegisterProperty<RoleEditList>(o => o.Roles);

        public RoleEditList Roles
        {
            get { return this.GetProperty(RolesProperty); }
            set { this.SetProperty(RolesProperty, value); }
        }

        #region Business Properties

        

        [Required]
        public string Firstname
        {
            get { return this.GetProperty(FirstnameProperty); }
            set { this.SetProperty(FirstnameProperty, value); }
        }

        private static readonly PropertyInfo<string> FirstnameProperty =
            RegisterProperty<string>(o => o.Firstname);

        public int Id
        {
            get { return this.GetProperty(IdProperty); }
        }

        private static readonly PropertyInfo<int> IdProperty =
            RegisterProperty<int>(o => o.Id);

        [Required]
        public string Lastname
        {
            get { return this.GetProperty(LastnameProperty); }
            set { this.SetProperty(LastnameProperty, value); }
        }

        private static readonly PropertyInfo<string> LastnameProperty =
            RegisterProperty<string>(o => o.Lastname);

        public byte[] Password
        {
            get { return this.GetProperty(PasswordProperty); }
            set { this.SetProperty(PasswordProperty, value); }
        }

        private static readonly PropertyInfo<byte[]> PasswordProperty =
            RegisterProperty<byte[]>(o => o.Password);


        [Required]
        public string Username
        {
            get { return this.GetProperty(UsernameProperty); }
            set { this.SetProperty(UsernameProperty, value); }
        }

        private static readonly PropertyInfo<string> UsernameProperty =
            RegisterProperty<string>(o => o.Username);

        #endregion

        #region Factory Methods

        public static UserEdit Get(int id)
        {
            return DataPortal.Fetch<UserEdit>(id);
        }

        #endregion

        private static void AddObjectAuthorizationRules()
        {
            BusinessRules.AddRule(typeof(UserEdit), new IsInRole(AuthorizationActions.GetObject, "Admin"));
            BusinessRules.AddRule(typeof(UserEdit), new IsInRole(AuthorizationActions.CreateObject, "Admin"));
            BusinessRules.AddRule(typeof(UserEdit), new IsInRole(AuthorizationActions.EditObject, "Admin"));
            BusinessRules.AddRule(typeof(UserEdit), new IsInRole(AuthorizationActions.DeleteObject, "Admin"));
        }

        private User ToEntity()
        {
            ISet<Role> roles = new HashSet<Role>();
            foreach (var role in this.ReadProperty(RolesProperty))
            {
                roles.Add(new Role(role.Id, role.Name));
            }
            return new User
                {
                    Id = this.ReadProperty(IdProperty),
                    Firstname = this.ReadProperty(FirstnameProperty),
                    Lastname = this.ReadProperty(LastnameProperty),
                    Passwort = this.ReadProperty(PasswordProperty),
                    Roles = roles,
                    Username = this.ReadProperty(UsernameProperty)
                };
        }

        #region Data Access

        private void DataPortal_Fetch(int id)
        {
            using (var ctx = new HaushaltsbuchContext())
            {
                var entity = ctx.Users.Include(u =>  u.Roles).Single(u => u.Id == id);

                this.LoadProperty(IdProperty, entity.Id);
                this.LoadProperty(FirstnameProperty, entity.Firstname);
                this.LoadProperty(LastnameProperty, entity.Lastname);
                this.LoadProperty(UsernameProperty, entity.Username);
                this.LoadProperty(PasswordProperty, entity.Passwort);

                var roles = RoleEditList.Get(entity.Roles.ToArray());
                this.LoadProperty(RolesProperty, roles);
                
            }
        }

        private void DataPortal_Update()
        {
            using (var ctx = new HaushaltsbuchContext())
            {
                var entity = this.ToEntity();
                ctx.Entry(entity).State = EntityState.Modified;
                ctx.SaveChanges();
            }
        }

        #endregion
    }
}